/**
 * MCP协议处理器
 *
 * 实现完整的MCP协议规范，独立于特定SDK实现
 * 支持JSON-RPC 2.0通信
 */

import type { Tool } from './tool-schema.js';
import { JsonSchemaAdapter } from './json-schema-adapter.js';
import { JsonSchemaValidator } from './json-validator.js';

// JSON-RPC 2.0 类型定义
interface JsonRpcRequest {
  jsonrpc: '2.0';
  id: string | number | null;
  method: string;
  params?: any;
}

interface JsonRpcResponse {
  jsonrpc: '2.0';
  id: string | number | null;
  result?: any;
  error?: JsonRpcError;
}

interface JsonRpcError {
  code: number;
  message: string;
  data?: any;
}

// MCP 特定类型
interface MCPInitializeParams {
  protocolVersion: string;
  capabilities: {
    tools?: boolean;
    resources?: boolean;
    prompts?: boolean;
  };
  clientInfo?: {
    name: string;
    version: string;
  };
}

// MCP 工具调用响应类型
interface MCPToolCallResponse extends JsonRpcResponse {
  result?: {
    content: Array<{
      type: 'text' | 'image' | 'resource';
      text?: string;
      data?: string;
      mimeType?: string;
      uri?: string;
    }>;
    isError?: boolean;
  };
}

export class MCPProtocolHandler {
  private tools: Map<string, Tool> = new Map();
  private schemaAdapter = new JsonSchemaAdapter();
  private validator = new JsonSchemaValidator();

  private readonly protocolVersion = '2024-11-05'; // MCP 协议版本
  private initialized = false;

  /**
   * 注册工具
   */
  registerTool(tool: Tool): void {
    this.tools.set(tool.name, tool);
  }

  /**
   * 注册多个工具
   */
  registerTools(tools: Tool[]): void {
    tools.forEach(tool => this.registerTool(tool));
  }

  /**
   * 处理JSON-RPC请求
   */
  async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    console.error(`[MCP] ${request.method} (id: ${request.id})`);
    
    try {
      // 验证基本的JSON-RPC格式
      if (request.jsonrpc !== '2.0') {
        return this.createErrorResponse(
          request.id,
          -32600,
          'Invalid Request: jsonrpc must be "2.0"'
        );
      }

      // 根据方法路由请求
      switch (request.method) {
        case 'initialize':
          return await this.handleInitialize(request);

        case 'tools/list':
          return await this.handleToolsList(request);

        case 'tools/call':
          return await this.handleToolCall(request);

        case 'notifications/initialized':
        case 'notifications/message':
          return await this.handleNotification(request);

        default:
          return this.createErrorResponse(
            request.id,
            -32601,
            `Method not found: ${request.method}`
          );
      }
    } catch (error) {
      return this.createErrorResponse(
        request.id,
        -32603,
        `Internal error: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  }

  /**
   * 处理初始化请求
   */
  private async handleInitialize(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    const params = request.params as MCPInitializeParams;

    // 验证协议版本
    if (!params?.protocolVersion) {
      return this.createErrorResponse(
        request.id,
        -32602,
        'Invalid params: protocolVersion is required'
      );
    }

    this.initialized = true;

    return {
      jsonrpc: '2.0',
      id: request.id,
      result: {
        protocolVersion: this.protocolVersion,
        capabilities: {
          tools: this.tools.size > 0 ? {} : undefined,
          resources: undefined,
          prompts: undefined,
        },
        serverInfo: {
          name: 'test-case-writer-mcp',
          version: '1.0.0',
        },
      },
    };
  }

  /**
   * 处理工具列表请求
   */
  private async handleToolsList(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    if (!this.initialized) {
      return this.createErrorResponse(request.id, -32002, 'Server not initialized');
    }

    const toolsList = Array.from(this.tools.values()).map(tool => ({
      name: tool.name,
      description: tool.description,
      inputSchema: tool.schema ? this.schemaAdapter.toJsonSchema(tool.schema) : {
        type: "object",
        properties: {},
        required: []
      },
    }));

    return {
      jsonrpc: '2.0',
      id: request.id,
      result: {
        tools: toolsList,
      },
    };
  }

  /**
   * 处理工具调用请求
   */
  private async handleToolCall(request: JsonRpcRequest): Promise<MCPToolCallResponse> {
    if (!this.initialized) {
      return this.createErrorResponse(request.id, -32002, 'Server not initialized');
    }

    const { name, arguments: params } = request.params || {};

    if (!name) {
      return this.createErrorResponse(request.id, -32602, 'Invalid params: name is required');
    }

    const tool = this.tools.get(name);
    if (!tool) {
      return this.createErrorResponse(request.id, -32602, `Tool not found: ${name}`);
    }

    // 使用 JSON Schema 验证参数
    if (tool.schema) {
      const jsonSchema = this.schemaAdapter.toJsonSchema(tool.schema);
      const validationResult = this.validator.validate(params || {}, jsonSchema);

      if (!validationResult.valid) {
        const errorDetails = validationResult.errors?.join('; ') || 'Validation failed';
        return this.createErrorResponse(request.id, -32602, `Invalid params: ${errorDetails}`);
      }
    }

    try {
      // 执行工具
      const result = await tool.execute(params || {});

      return {
        jsonrpc: '2.0',
        id: request.id,
        result: {
          content: [
            {
              type: 'text',
              text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
            },
          ],
          isError: false,
        },
      };
    } catch (error) {
      // 工具执行错误应该返回业务层错误（isError: true），而不是协议层错误
      let errorMessage: string;
      let errorStack: string | undefined;
      
      if (error instanceof Error) {
        errorMessage = error.message;
        errorStack = error.stack;
      } else if (typeof error === 'string') {
        errorMessage = error;
        errorStack = undefined;
      } else {
        errorMessage = String(error) || 'Unknown error';
        errorStack = undefined;
      }

      return {
        jsonrpc: '2.0',
        id: request.id,
        result: {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                error: errorMessage,
                code: 'TOOL_EXECUTION_ERROR',
                timestamp: new Date().toISOString(),
                stack: errorStack,
              }),
            },
          ],
          isError: true,
        },
      };
    }
  }

  /**
   * 处理通知（通常不需要响应）
   */
  private async handleNotification(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    console.error(`[MCP] Notification: ${request.method}`);
    
    // 特殊处理initialized通知
    if (request.method === 'notifications/initialized') {
      console.error('[MCP] Client initialization completed');
    }

    // MCP通知通常不需要响应，但如果有ID就返回空结果
    if (request.id !== null && request.id !== undefined) {
      // 这里返回空对象而不是null，符合JSON-RPC规范
      return {
        jsonrpc: '2.0',
        id: request.id,
        result: {},
      };
    }

    // 真正的通知没有ID，不返回响应
    return null as any;
  }

  /**
   * 创建错误响应
   */
  private createErrorResponse(
    id: string | number | null,
    code: number,
    message: string,
    data?: any
  ): JsonRpcResponse {
    return {
      jsonrpc: '2.0',
      id,
      error: {
        code,
        message,
        data,
      },
    };
  }

  /**
   * 处理标准输入输出流
   */
  async handleStdio(input: NodeJS.ReadableStream, output: NodeJS.WritableStream): Promise<void> {
    const readline = await import('readline');
    const rl = readline.createInterface({
      input,
      output: output as any,
      terminal: false,
    });

    rl.on('line', async line => {
      try {
        const request = JSON.parse(line) as JsonRpcRequest;
        const response = await this.handleRequest(request);

        // 只有非通知请求才返回响应
        if (response) {
          const responseString = JSON.stringify(response) + '\n';
          output.write(responseString);
          // 强制刷新输出流
          if (typeof (output as any).flush === 'function') {
            (output as any).flush();
          }
        }
      } catch (error) {
        const errorResponse = this.createErrorResponse(null, -32700, 'Parse error');
        output.write(JSON.stringify(errorResponse) + '\n');
      }
    });
  }

  /**
   * 处理HTTP请求（用于HTTP传输）
   */
  async handleHttp(body: string): Promise<string> {
    try {
      const request = JSON.parse(body) as JsonRpcRequest;
      const response = await this.handleRequest(request);
      return JSON.stringify(response);
    } catch (error) {
      const errorResponse = this.createErrorResponse(null, -32700, 'Parse error');
      return JSON.stringify(errorResponse);
    }
  }
}

// 标准错误代码
export const JSON_RPC_ERROR_CODES = {
  PARSE_ERROR: -32700,
  INVALID_REQUEST: -32600,
  METHOD_NOT_FOUND: -32601,
  INVALID_PARAMS: -32602,
  INTERNAL_ERROR: -32603,
  SERVER_ERROR: -32000,
} as const;
